package ace.cmp.spring.data.jdbc.querydsl.core;

import com.querydsl.core.types.Path;
import com.querydsl.core.types.dsl.SimpleExpression;
import com.querydsl.sql.RelationalPath;
import com.querydsl.sql.RelationalPathBase;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.List;
import org.springframework.data.relational.core.mapping.RelationalPersistentEntity;

/**
 * @author caspar
 * @date 2023/8/25 9:51
 */
public interface QuerydslRelationHelper {

  /**
   * 获取 {@link org.springframework.data.annotation.Id}的属性值
   *
   * @param entity 实体
   * @param <Id>   id类型
   * @param <T>    实体类型
   * @return 获取失败 null
   */
  <Id, T> Id getEntityId(T entity);

  /**
   * 设置 {@link org.springframework.data.annotation.Id}的属性值
   *
   * @param entity 实体
   * @param id     id值
   * @param <Id>   id类型
   * @param <T>    实体类型
   */
  <Id, T> void setEntityId(T entity, Id id);

  /**
   * 获取 {@link RelationalPathBase},根据实体类型
   *
   * @param entityType
   * @return
   */
  <T> RelationalPathBase<T> getRelationalPathBaseByEntityType(Class<T> entityType);

  /**
   * 获取 实体的查询Q类型,根据实体类型
   *
   * @param entityType
   * @return
   */
  <T> Class<T> getQueryClassByEntityType(Class<T> entityType);

  /**
   * 获取 {@link RelationalPathBase},根据实体的查询Q类型
   *
   * @param queryClass
   * @return
   */
  <T> RelationalPathBase<T> getRelationalPathBaseFromQueryClass(Class<T> queryClass);

  /**
   * @param entityType
   * @param <T>
   * @return
   */
  <T> RelationalPersistentEntity<T> getRelationalPersistentEntityByEntityType(Class<T> entityType);

  /**
   * 获取逻辑删除标记字段
   *
   * @param entityType
   * @return
   */
  SimpleExpression getLogicDeleteExpression(Class entityType);

  /**
   * 获取主键
   *
   * @param entityType
   * @param <T>
   * @return
   */
  <T> Path getPrimaryKeyPath(Class<T> entityType);

  /**
   * 获取主键查询表达式
   *
   * @param entityType
   * @param <T>
   * @return
   */
  <T> List<SimpleExpression> getPrimaryKeyExpressions(Class<T> entityType);

  /**
   * 获取主键查询表达式
   *
   * @param entityType
   * @param <T>
   * @return
   */
  <T> SimpleExpression getPrimaryKeyExpression(Class<T> entityType);

  /**
   * 获取逻辑删除 {@link RelationalPath}
   *
   * @param entityType
   * @return
   */
  <T> Path getLogicDeletePath(Class<T> entityType);

  /**
   * 获取字段关联的 {@link RelationalPath}
   *
   * @param entityType
   * @param fieldName
   * @param <T>
   * @return
   */
  <T> Path getPathByEntityTypeAndFieldName(Class<T> entityType, String fieldName);

  /**
   * 获取字段关联的 {@link RelationalPath}
   *
   * @param entityType
   * @param annClass   注解
   * @return
   * @throws IllegalArgumentException 查询到有多项符合条件
   */
  Path getPathByEntityTypeAndAnnotation(Class<?> entityType, Class<? extends Annotation> annClass);

  /**
   * 根据逻辑删除注解 {@link ace.cmp.spring.data.jdbc.querydsl.core.annotations.LogicDelete}
   *
   * @param entityType
   * @return
   */
  Object getLogicNotDeleteFlagValue(Class entityType);

  /**
   * 查找逻辑删除字段的值
   *
   * @param object 查询对象
   * @return 逻辑删除字段的值
   */
  Object getLogicDeleteFieldValue(Object object);

  /**
   * 查找逻辑删除字段
   *
   * @param entityType 查询对象类型
   * @return 逻辑删除字段
   */
  Field getLogicDeleteField(Class entityType);

  /**
   * 查询指定字段,根据注解.
   *
   * @param entityType 查询对象类型
   * @param annClass   注解
   * @return 字段
   * @throws IllegalArgumentException 查询到有多项符合条件
   */
  Field getFieldByAnnotation(Class<?> entityType, Class<? extends Annotation> annClass);

  /**
   * 查询指定字段,根据字段名.
   *
   * @param entityType 查询对象类型
   * @param name       字段名
   * @return 字段
   */
  Field getFieldByName(Class<?> entityType, String name);
}
